home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / dte5_1.zip / BLOCK.C next >
C/C++ Source or Header  |  1991-02-06  |  39KB  |  1,231 lines

  1. /*
  2.  * Written by Douglas Thomson (1989/1990)
  3.  *
  4.  * This source code is released into the public domain.
  5.  */
  6.  
  7. /*
  8.  * Name:    dte - Doug's Text Editor program - block commands module
  9.  * Purpose: This file contains all the commands than manipulate blocks.
  10.  * File:    block.c
  11.  * Author:  Douglas Thomson
  12.  * System:  this file is intended to be system-independent
  13.  * Date:    October 1, 1989
  14.  */
  15.  
  16. #ifdef HPXL
  17. #include "commonh"
  18. #include "utilsh"
  19. #include "blockh"
  20. #else
  21. #include "common.h"
  22. #include "utils.h"
  23. #include "block.h"
  24. #endif
  25.  
  26. /*
  27.  * prototypes for all functions in this file
  28.  */
  29. void set_marker ARGS((windows *window, int n));
  30. void mark_start ARGS((windows *window));
  31. void mark_end ARGS((windows *window));
  32. void prepare_block ARGS((windows *window));
  33. void block_move ARGS((windows *window));
  34. void block_copy ARGS((windows *window));
  35. void block_read ARGS((windows *window, int fixup));
  36. int check_block ARGS((windows *window));
  37. void block_delete ARGS((windows *window));
  38. void block_indent ARGS((windows *window));
  39. void block_unindent ARGS((windows *window));
  40. void block_write ARGS((windows *window));
  41. void block_print ARGS((windows *window));
  42.  
  43. /*
  44.  * Name:    set_marker
  45.  * Purpose: To record the position of a marker in the file.
  46.  * Date:    October 1, 1989
  47.  * Passed:  window: information required to access current window
  48.  *          n:      the number of the marker to set
  49.  * Notes:   n must be in the range 0..9
  50.  */
  51. void set_marker(window, n)
  52. windows *window;
  53. int n;
  54. {
  55.     int col;    /* cursor column, or end of line, whichever is less */
  56.     int len;    /* length of current line */
  57.  
  58.     if (g_status.copied) {
  59.         /*
  60.          * current line buffer is active, so set the buffer marker
  61.          */
  62.         if ((col = window->ccol) > (len = linelen(g_status.line_buff))) {
  63.             /*
  64.              * markers can only be placed where there is actually some
  65.              *  text. If the cursor is beyond the end of the line, then
  66.              *  the marker must be set at the end of the line
  67.              */
  68.             col = len;
  69.         }
  70.         g_status.buff_marker[n] = g_status.line_buff + col;
  71.     }
  72.     else {
  73.         /*
  74.          * work directly with main text
  75.          */
  76.         if ((col = window->ccol) > (len = linelen(window->cursor))) {
  77.             col = len;
  78.         }
  79.         window->file_info->marker[n] = window->cursor + col;
  80.     }
  81. }
  82.  
  83. /*
  84.  * Name:    mark_start
  85.  * Purpose: To record the position of the start of the block in the file.
  86.  * Date:    October 1, 1989
  87.  * Passed:  window: information required to access current window
  88.  * Notes:   This differs slightly from the setting of a normal mark,
  89.  *           in that if we are using the current line buffer, the main
  90.  *           text start marker must be modified also. (This may not
  91.  *           still be necessary?)
  92.  */
  93. void mark_start(window)
  94. windows *window;
  95. {
  96.     int col;    /* cursor column, or end of line, whichever is less */
  97.     int len;    /* length of current line */
  98.  
  99.     /*
  100.      * if the end of the block has already been marked, then the block
  101.      *  must now become visible
  102.      */
  103.     if (window->file_info->marker[END_BLOCK]) {
  104.         window->file_info->visible = TRUE;
  105.     }
  106.  
  107.     if (g_status.copied) {
  108.         if ((col = window->ccol) > (len = linelen(g_status.line_buff))) {
  109.             col = len;
  110.         }
  111.         window->file_info->marker[START_BLOCK] = window->cursor;
  112.         g_status.buff_marker[START_BLOCK] = g_status.line_buff + col;
  113.     }
  114.     else {
  115.         if ((col = window->ccol) > (len = linelen(window->cursor))) {
  116.             col = len;
  117.         }
  118.         window->file_info->marker[START_BLOCK] = window->cursor + col;
  119.     }
  120. }
  121.  
  122. /*
  123.  * Name:    mark_end
  124.  * Purpose: To record the position of the end of the block in the file.
  125.  * Date:    October 1, 1989
  126.  * Passed:  window: information required to access current window
  127.  * Notes:   This differs slightly from the setting of a normal mark,
  128.  *           in that if we are using the current line buffer, the main
  129.  *           text end marker must be modified also.
  130.  */
  131. void mark_end(window)
  132. windows *window;
  133. {
  134.     int col;    /* cursor column, or end of line, whichever is less */
  135.     int len;    /* length of current line */
  136.  
  137.     if (window->file_info->marker[START_BLOCK]) {
  138.         window->file_info->visible = TRUE;
  139.     }
  140.     if (g_status.copied) {
  141.         if ((col = window->ccol) > (len = linelen(g_status.line_buff))) {
  142.             col = len;
  143.         }
  144.         window->file_info->marker[END_BLOCK] = window->cursor;
  145.         g_status.buff_marker[END_BLOCK] = g_status.line_buff + col;
  146.     }
  147.     else {
  148.         if ((col = window->ccol) > (len = linelen(window->cursor))) {
  149.             col = len;
  150.         }
  151.         window->file_info->marker[END_BLOCK] = window->cursor + col;
  152.     }
  153. }
  154.  
  155. /*
  156.  * Name:    prepare_block
  157.  * Purpose: To prepare a window/file for a block read, move or copy.
  158.  * Date:    October 10, 1989
  159.  * Passed:  window: information required to access current window
  160.  * Notes:   The main complication is that the cursor may be beyond the end
  161.  *           of the current line, in which case extra padding spaces have
  162.  *           to be added before the block operation can take place.
  163.  */
  164. void prepare_block(window)
  165. windows *window;
  166. {
  167.     text_ptr source;        /* source for block moves */
  168.     text_ptr dest;          /* destination for block moves */
  169.     int pad;                /* amount of padding to be added */
  170.     int len;                /* length (usually of current line) */
  171.     int cr;                 /* does current line end with \n? */
  172.     long number;            /* number of characters for block moves */
  173.  
  174.     /*
  175.      * if cursor was beyond the end of the actual line, then add
  176.      *  padding first.
  177.      *
  178.      * work on the current line buffer until padding is sorted out.
  179.      */
  180.     copy_line(window);
  181.     if (window->ccol > (len = linelen(g_status.line_buff))) {
  182.         /*
  183.          * work out how much padding is required to extend the current
  184.          *  line to the cursor position
  185.          */
  186.         if (g_status.line_buff[len] == '\n') {
  187.             cr = 1;
  188.         }
  189.         else {
  190.             cr = 0;
  191.         }
  192.         pad = window->ccol - len;
  193.  
  194.         /*
  195.          * check that there is room in the current line - should never
  196.          *  give any problems...
  197.          */
  198.         if (len + pad + cr >= BUFF_SIZE) {
  199.             error(WARNING, "too far right");
  200.             return;
  201.         }
  202.  
  203.         /*
  204.          * make room for the padding spaces, and fix the markers
  205.          */
  206.         source = g_status.line_buff + window->ccol - pad;
  207.         dest = source + pad;
  208.         number = len + pad - window->ccol + 1 + cr;
  209.         hw_move(dest, source, number);
  210.         fix_marks(window, source, (long) pad);
  211.  
  212.         /*
  213.          * insert the padding spaces
  214.          */
  215.         while (pad--) {
  216.             *source++ = ' ';
  217.         }
  218.     }
  219.     un_copy_line(window);
  220.  
  221.     /*
  222.      * The cursor is now somewhere in the main text block, so there
  223.      *  are no major complications.
  224.      */
  225. }
  226.  
  227. /*
  228.  * Name:    move_block
  229.  * Purpose: To move the marked block from its current position to the
  230.  *           cursor position.
  231.  * Date:    October 1, 1989
  232.  * Passed:  window: information required to access current window
  233.  */
  234. void block_move(window)
  235. windows *window;
  236. {
  237.     text_ptr source;        /* source for block moves */
  238.     text_ptr dest;          /* destination for block moves */
  239.     long number;            /* number of characters for block moves */
  240.     int len;                /* length (usually of current line) */
  241.     int add;                /* characters being added from another line */
  242.     long block_len;         /* length of the block */
  243.     text_ptr orig;          /* cursor location in text */
  244.     text_ptr block_text;    /* place block is temporarily moved to */
  245.     text_ptr block_dest;    /* place block must finish up in */
  246.     text_ptr fix_pos;       /* origin for marker fixup */
  247.  
  248.     if (!window->file_info->visible) {
  249.